<?php
    /*

     Version: MPL 1.1

     Software distributed under the License is distributed on an "AS IS"
     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
     License for the specific language governing rights and limitations
     under the License.

     The Original Code is KASSIOP Framework.

     The Initial Developer of the Original Code is SURIAN Nicolas (aka NairuS) <me@nairus.fr>.
     Portions created by the Initial Developer are Copyright (C) 2010
     The Initial Developer. All Rights Reserved.

     Contributor(s):

     Alternatively, the contents of this file may be used under the terms
     of the MPL license Version 1.1 (the  "MPL" License"), in which case the
     provisions of Version: MPL 1.1 License are applicable instead of those
     above.  If you wish to allow use of your version of this file only
     under the terms of the MPL License and not to allow others to use
     your version of this file under the MPL, indicate your decision by
     deleting  the provisions above and replace  them with the notice and
     other provisions required by the MPL License.  If you do not delete
     the provisions above, a recipient may use your version of this file
     under either the MPL License.

     The contents of this file are subject to the Mozilla Public License
     Version 1.1 (the "License"); you may not use this file except in
     compliance with the License. You may obtain a copy of the License at
     http://www.mozilla.org/MPL/

    */

    /**
     * Display and manage articles.
     *
     * @package    kassiop.core
     * @subpackage controllers
     *
     * @author NairuS
     * @version 1.2 $Rev: 90 $ $Date: 2011-01-16 09:23:26 +0000 (Sun, 16 Jan 2011) $ $Author: nicolas.surian $
     *
     */
    abstract class Controller
    {
        /**
         * Create an instance of the controller.
         *
         * @param Configuration      $config      the current configuration of the application.
         * @param CredentialsManager $credendials the current credentials manager for the application.
         */
        public function __construct( Configuration $config, CredentialsManager $credendials = null )
        {
            Configuration::includeBootstrap();

            // init the contructor.
            $this->config      = $config ;
            $this->credendials = $credendials ;
            $this->files       = isset( $_FILES ) ? $_FILES                  : array() ;
            $this->getParams   = isset( $_GET )   ? $this->doClean( $_GET )  : array() ;
            $this->layout      = 'default' ;
            $this->postParams  = isset( $_POST )  ? $this->doClean( $_POST ) : array() ;
            $this->sessionName = $this->config->getSessionName() ;

            // add the current role of the user connected.
            $user       = SessionManager::read( SessionManager::buildSessionVar( $this->sessionName, SessionManager::USER_INFOS ) ) ;
            $this->role = $user instanceof UserVO ? $user->role : null;

            // set the flashes message.
            $flashes = SessionManager::read( SessionManager::buildSessionVar( $this->sessionName, FlashesVars::NAME ) ) ;
            if( is_array( $flashes ) )
            {
                $this->setFlashes( $flashes[FlashesVars::MESSAGE], $flashes[FlashesVars::LEVEL] );
            }
        }

        /**
         * The reference of the application Configuration.
         *
         * @var Configuration
         */
        public $config ;

        /**
         * The reference of the application CredentialsManager.
         *
         * @var CredentialsManager
         */
        public $credendials ;

        /**
         * Defines the name of the current layout.
         *
         * @var string
         */
        public $layout ;

        /**
         * Defines the name of the current session
         * .
         * @var string
         */
        public $sessionName ;

        /**
         * Store the vars to send in the view.
         *
         * @var array
         */
        public $viewVars = array() ;

        /**
         * Store the $_FILES params.
         *
         * @var array
         */
        protected $files = array() ;

        /**
         * Defines the flashes message to display.
         *
         * @var array
         */
        protected $flashVars;

        /**
         * Store the $_GET params.
         *
         * @var array
         */
        protected $getParams = array() ;

        /**
         * Store the $_POST params.
         *
         * @var array
         */
        protected $postParams = array() ;

        /**
         * The current RoleVO of the user.
         *
         * @var RoleVO
         */
        protected $role ;

        /**
         * An instance of the service.
         *
         * @var ServicesMysql
         */
        protected $service ;

        /**
         * Defines all the key to clean in a array.
         *
         * @var array
         */
        private static $_keysToClean = array( 'submit' ) ;

        /**
         * Return the current action loaded.
         *
         * @return string
         */
        public function getAction()
        {
            return $this->config->action ;
        }

        /**
         * Returns the array of flash message to extract in the view.
         *
         * @return array
         */
        public function getFlashes()
        {
            return !empty( $this->flashVars ) ? $this->flashVars : array() ;
        }

        /**
         * Return the current application.
         *
         * @return string
         */
        public function getApplication()
        {
            return $this->config->application ;
        }

        /**
         * Return the current module.
         *
         * @return string
         */
        public function getModule()
        {
            return $this->config->module ;
        }

        /**
         * Gets the current service of the controller.
         * @desc Override this method to return the right type of service.
         *
         * @return ServicesMysql
         */
        public function getService()
        {
            return $this->service ;
        }

        /**
         * Sets the flashes message to display.
         *
         * @param  string $message
         * @return void
         */
        public function setFlashes( $message, $level = FlashesVars::INFO )
        {
            $this->flashVars[FlashesVars::MESSAGE] = (string)$message ;
            $this->flashVars[FlashesVars::LEVEL]   = (string)$level ;

            SessionManager::write( SessionManager::buildSessionVar( $this->sessionName, FlashesVars::NAME ), $this->flashVars ) ;
        }


        /**
         * Render the current layout and set the vars to the view.
         *
         * @param Configuration $config
         * @return void
         */
        public function render()
        {

            if( method_exists( $this, $this->getAction() ) )
            {
                // set the action to launch.
                $action = $this->getAction() ;

                // launch the action.
                if( $this->$action() != View::NONE )
                {
                    // set the layout
                    $this->config->setLayout( $this->layout ) ;
                    $layout = $this->config->getLayout() ;
                    $view   = $this->config->getPage() ;

                    if( $view !== false && $layout !== false )
                    {
                        // set the view vars
                        extract( $this->viewVars ) ;

                        // set the flashes messages if exists.
                        $flashes = $this->getFlashes() ;
                        if( !empty( $flashes ) )
                        {
                            // send flashes message to the view.
                            extract( array( 'flashes' => $flashes ) ) ;

                            // remove all flashes messages in memory.
                            $this->flashVars = array() ;
                            SessionManager::remove( SessionManager::buildSessionVar( $this->sessionName, FlashesVars::NAME ) ) ;
                        }
                        include $layout ;
                    }
                    else
                    {
                        if( $view === false )
                        {
                            $message = 'The view specified <b>"' . $this->getModule() . '/a/' . $this->getAction() .'"</b>doesn\'t exist!' ;
                            SessionManager::write( 'error404', $message ) ;
                        }
                        else
                        {
                            $message = 'The layout specified <b>"' . $this->layout .'"</b>doesn\'t exist!' ;
                            SessionManager::write( 'error404', $message ) ;
                        }
                        $this->redirect( $this->config->getDefaultModule(), 'error404' ) ;
                    }
                }
            }
            else
            {
                $message = 'The action specified <b>"' . $this->getAction() .'"</b> doesn\'t exist in the controller <b>"' . get_class( $this ) . '"</b>!' ;
                SessionManager::write('error404', $message ) ;
                $this->redirect( $this->config->getDefaultModule(), 'error404' ) ;
            }
        }

        /**
         * Clean the file to upload
         *
         * @param  string $key
         * @param  string $method
         *
         * @return array of the post params cleaned.
         */
        protected function cleanFile( $key, $method = 'post' )
        {
            $fileSent = false;
            $file     = $this->hasFile( $key ) ? $this->files[$key] : null;
            $params   = $method == 'post' ? $this->getPostParameters() : $this->getGetParameters() ;
            if( $file !== null )
            {
                $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type');
                $keys     = array_keys($file);
                sort($keys);
                if( $fileKeys == $keys && !empty( $file['tmp_name'] ) )
                {
                    if( isset( $params[ $key ] ) )
                    {
                        $params['temp_' . $key] = $params[$key];
                    }
                    $params[$key] = $file;
                }
            }
            else
            {
                var_dump('here');
            }
            return $params;
        }

        /**
         * Clean Get Post or other paramaters sent.
         *
         * @param array $params
         * @return array of params
         */
        protected function doClean( array $params )
        {
            foreach( self::$_keysToClean as $key )
            {
                if( key_exists( $key , $params ) )
                {
                    unset( $params[$key] );
                }
            }
            return $params ;
        }

        /**
         * Returns an array of files to upload.
         * @return array of files to upload.
         */
        protected function getFiles()
        {
            return $this->files ;
        }

        /**
         * Returns the get parameters stored.
         *
         * @return array of get parameters.
         */
        protected function getGetParameters()
        {
            return $this->getParams ;
        }

        /**
         * Returns the get parameter passed-in.
         *
         * @param string $key   the name of the parameter to return.
         * @return mixed of the get parameter value.
         */
        protected function getGetParameter( $key )
        {
            return $this->getParams[$key] ;
        }

        /**
         * Returns the post parameters stored.
         *
         * @return array of post parameters.
         */
        protected function getPostParameters()
        {
            return $this->postParams ;
        }

        /**
         * Returns the post parameter passed-in.
         *
         * @param string $key   the name of the parameter to return.
         * @return mixed of the post parameter value.
         */
        protected function getPostParameter( $key )
        {
            return isset( $this->postParams[$key] ) ? $this->postParams[$key] : null ;
        }

        /**
         * Checks if the file passed-in exists.
         *
         * @param string $key
         * @return boolean
         */
        protected function hasFile( $key )
        {
            return array_key_exists( $key, $this->files ) ;
        }

        /**
         * Checks if there is some files to send.
         *
         * @return boolean
         */
        protected function hasFiles()
        {
            return !empty( $this->files ) ;
        }

        /**
         * Checks if the get parameter passed-in exists.
         *
         * @param string $key
         * @return boolean
         */
        protected function hasGetParameter( $key )
        {
            return array_key_exists( $key, $this->getParams ) ;
        }

        /**
         * Checks if there is some get parameters in the request.
         *
         * @return boolean
         */
        protected function hasGetParameters()
        {
            return !empty( $this->getParams ) ;
        }

        /*
         * Checks if the post parameter passed-in exists.
         *
         * @param string $key
         * @return boolean
         */
        protected function hasPostParameter( $key )
        {
            return array_key_exists( $key, $this->postParams ) ;
        }

        /*
         * Checks if there is some post parameters in the request.
         *
         * @return boolean
         */
        protected function hasPostParameters()
        {
            return !empty( $this->postParams ) ;
        }

        /**
         * Checks if the user is authorized to see the current page.
         *
         * @return boolean true if the user is authorized to display the current page or redirect on login page.
         */
        protected function isAuthorized()
        {
            if( SessionManager::isAuthentified( $this->sessionName ) )
            {
                if( $this->credendials instanceof CredentialsManager )
                {
                    $action = $this->getAction() != 'index' ? '.' . $this->getAction() : null ;
                    return $this->credendials->hasCredential( $this->getModule() . $action, $this->role ) ;
                }
                else
                {
                    return true ;
                }
            }
           else
            {
                $this->redirect( 'main', 'login' ) ;
            }
        }

        /**
         * Redirect the current page to the uri passed-in.
         *
         * @param string $uri
         * @return void
         */
        protected function navigateTo( $uri )
        {
            UriHelper::redirect( $uri ) ;
        }

        /**
         * Redirect the current page to the module and the action passed-in
         *
         * @param string $module
         * @param void $action
         * @return void
         */
        protected function redirect( $module = 'main', $action = 'index' )
        {
            UriHelper::redirect( UriHelper::get( $module, $action ) ) ;
        }

        /**
         * Set a var to send in the view.
         * @param $params
         * @return void
         */
        protected function set( $name, $value )
        {
            $this->viewVars[$name] = $value ;
        }
    }
?>